-
Notifications
You must be signed in to change notification settings - Fork 342
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add type hints to all remaining top-level files #1150
Conversation
@@ -147,15 +147,14 @@ def pretty_print_probabilities(self, decimal_digits=2): | |||
outcome_dict[outcome] = prob | |||
return outcome_dict | |||
|
|||
def pretty_print(self, decimal_digits=2): | |||
def pretty_print(self, decimal_digits: int = 2) -> str: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wicked smart type inference
but who type checks the types? |
sorry that was a bad "who watches the watchmen" joke |
pyquil/wavefunction.py
Outdated
return len(self.amplitudes).bit_length() - 1 | ||
|
||
def __iter__(self): | ||
def __iter__(self) -> Any: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Iterator[complex]
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, this is because numpy is a big ball of untyped anarchy, isn't it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could we instead cast
the returned value to Iterator[complex]
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tried it: mypy doesn't complain, but we also don't actually check that all values in amplitude_vector
are complex
in __init__
, but that is the documented type in the docstring. otoh, Wavefunction.zeros
appears to create an amplitude_vector
of float
s so maybe complex
is too restrictive...
mymypy? yourpy? |
1b555c3
to
ef81266
Compare
In fact, mypy is type-checked by itself, e.g. https://github.com/python/mypy/blob/master/mypy/checker.py. |
pyquil/operator_estimation.py
Outdated
@@ -305,7 +306,7 @@ def measure_observables( | |||
# either the first column, second column, or both and multiplying along the row. | |||
for setting in settings: | |||
# Get the term's coefficient so we can multiply it in later. | |||
coeff = complex(setting.out_operator.coefficient) | |||
coeff = complex(cast(complex, setting.out_operator.coefficient)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not obvious to me -- why is this needed?
ef81266
to
e246fc9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm. all comments can be of # type: ignore
pyquil/paulis.py
Outdated
pow = result * self | ||
assert isinstance(pow, PauliTerm) | ||
result = pow |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mypy is weird.
normally I prefer isinstance
checks, but maybe a cast
would be better inside this loop?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah this one threw me for a l00p (pun intended). I'll try the cast
idea
pyquil/paulis.py
Outdated
@@ -330,24 +340,23 @@ def __add__(self, other: Union[PauliDesignator, ExpressionDesignator]) -> "Pauli | |||
else: # is a Number | |||
return self + PauliTerm("I", 0, other) | |||
|
|||
def __radd__(self, other: ExpressionDesignator) -> "PauliTerm": | |||
def __radd__(self, other: ExpressionDesignator) -> "PauliSum": | |||
"""Adds this PauliTerm with a Number. | |||
:param other: A Number | |||
:returns: A new PauliTerm |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PauliSum
pyquil/paulis.py
Outdated
return PauliTerm("I", 0, other) + self | ||
|
||
def __sub__(self, other: Union["PauliTerm", Number]) -> "PauliSum": | ||
def __sub__(self, other: Union["PauliTerm", ExpressionDesignator]) -> "PauliSum": | ||
"""Subtracts a PauliTerm from this one. | ||
:param other: A PauliTerm object or a Number |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
or an Expression ?
@@ -899,6 +917,8 @@ def exponential_map(term: PauliTerm) -> Callable[[float], Program]: | |||
:param term: A pauli term to exponentiate | |||
:returns: A function that takes an angle parameter and returns a program. | |||
""" | |||
assert isinstance(term.coefficient, (float, complex)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is a float
possible here? The type annotation on PauliTerm.coefficient
above says it's Union[Expression, complex]
and the __init__
normalizes any Number
to complex
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought so too, but it happens in the unit tests. Unclear to me how, but I think that's a problem for another time
pyquil/paulis.py
Outdated
@@ -964,14 +984,13 @@ def reverse_hack(p: Program) -> Program: | |||
highest_target_index = None | |||
|
|||
for index, op in pauli_term: | |||
assert isinstance(index, int) or isinstance(index, QubitPlaceholder) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assert isinstance(index, int) or isinstance(index, QubitPlaceholder) | |
assert isinstance(index, (int, QubitPlaceholder)) |
@@ -984,6 +1003,7 @@ def reverse_hack(p: Program) -> Program: | |||
# building rotation circuit | |||
quil_prog += change_to_z_basis | |||
quil_prog += cnot_seq | |||
assert isinstance(pauli_term.coefficient, (float, complex)) and highest_target_index is not None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto here re: float
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
pyquil/wavefunction.py
Outdated
return len(self.amplitudes).bit_length() - 1 | ||
|
||
def __iter__(self): | ||
def __iter__(self) -> Any: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could we instead cast
the returned value to Iterator[complex]
?
pyquil/wavefunction.py
Outdated
return self.amplitudes.__iter__() | ||
|
||
def __getitem__(self, index): | ||
def __getitem__(self, index: int) -> Any: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto here regarding cast
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ill give it a shot
self, op: str, index: PauliTargetDesignator, coefficient: ExpressionDesignator = 1.0 | ||
self, | ||
op: str, | ||
index: Optional[PauliTargetDesignator], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is there an extra Optional[]
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
because for sI()
the qubit argument is optional, so this can actually be None
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't it be index: Optional[PauliTargetDesignator] = None
then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not necessarily. Despite the name, it's valid (but rare) to have an Optional
required argument. Adding the = None
makes it a keyword arg, which means it gets a default value if the caller doesn't explicitly provide it. Whereas Optional
without = None
means you must explicitly pass None
when you want index
to be None
.
Making index
a keyword arg here should be backwards compatible, but since it was a required arg before adding the type hints, it seems reasonable for it to remain one after.
Description
Some typing odds and ends.
conftest.py
,pyquil/magic.py
, and all the files inpyquil/_parser
pyquil/paulis.py
pyquil/paulis.py
Next PR will be to deal with the API module, which is the only thing left.
Checklist
flake8
conventions.